package com.inspur.edp.lcm.metadata.common;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.inspur.edp.lcm.metadata.api.IMdExtRuleContent;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataHeader;
import com.inspur.edp.lcm.metadata.common.configuration.MdExtRuleSerializerHelper;
import com.inspur.edp.lcm.metadata.common.configuration.MetadataSerializerHelper;
import com.inspur.edp.lcm.metadata.common.utils.TestUtils;
import com.inspur.edp.lcm.metadata.spi.MdExtendRuleSerializer;
import com.inspur.edp.lcm.metadata.spi.MetadataContentSerializer;
import com.inspur.edp.metadata.rtcustomization.api.exception.LcmConfigResolveException;
import com.inspur.edp.metadata.rtcustomization.api.exception.LcmParseException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class MetadataSerializerTest {
    @Mock
    private MetadataSerializerHelper metadataSerializerHelper;

    @Mock
    private MetadataContentSerializer metadataContentSerializer;

    @Mock
    private IMetadataContent metadataContent;

    @Mock
    private MdExtRuleSerializerHelper mdExtRuleSerializerHelper;

    @Mock
    private MdExtendRuleSerializer mdExtendRuleSerializer;

    @Mock
    private IMdExtRuleContent mdExtRuleContent;

    private MetadataSerializer metadataSerializer = new MetadataSerializer();

    private ObjectMapper mapper = MetadataSerializer.getMapper();
    @Test
    void deserialize() throws JsonProcessingException {
        // null
        assertNull(metadataSerializer.deserialize("", GspMetadata.class));
        // 异常
        assertThrows(LcmParseException.class, () -> metadataSerializer.deserialize("a", GspMetadata.class));
        // 初始化元数据
        GspMetadata metadata = new GspMetadata(new MetadataHeader());
        metadata.getHeader().setType("type");
        // mock入参
        String fileString = MetadataSerializer.getMapper().writeValueAsString(metadata);

        // mock content
        TestUtils.setStaticFieldValue(MetadataSerializerHelper.class, "singleton", metadataSerializerHelper);
        when(metadataSerializerHelper.getManager(any())).thenReturn(metadataContentSerializer);
        when(metadataContentSerializer.DeSerialize(any())).thenReturn(metadataContent);

        // mock extendRule
        TestUtils.setStaticFieldValue(MdExtRuleSerializerHelper.class, "singleton", mdExtRuleSerializerHelper);
        when(mdExtRuleSerializerHelper.getManager(any())).thenReturn(mdExtendRuleSerializer);
        metadata.setExtendRule(mdExtRuleContent);
        when(mdExtendRuleSerializer.deSerialize(any())).thenReturn(mdExtRuleContent);

        // 调用方法
        GspMetadata metadata1 = metadataSerializer.deserialize(fileString, GspMetadata.class);
        assertEquals("type", metadata1.getHeader().getType());
    }

    @Test
    void deserializeMetadataContent() throws JsonProcessingException {
        // mock manager==null 分支
        TestUtils.setStaticFieldValue(MetadataSerializerHelper.class, "singleton", metadataSerializerHelper);
        when(metadataSerializerHelper.getManager(any())).thenReturn(null);
        assertThrows(LcmConfigResolveException.class, () -> metadataSerializer.deserializeMetadataContent(null, null));
        // mock manage.DeSerialize
        when(metadataSerializerHelper.getManager(any())).thenReturn(metadataContentSerializer);
        // mock metadataContent
        when(metadataContentSerializer.DeSerialize(any())).thenReturn(metadataContent);
        JsonNode jsonNode = mapper.readTree("{\"A\": \"a\"}");
        assertNotNull(metadataSerializer.deserializeMetadataContent("type", jsonNode.get("A")));
    }

    @Test
    void serialize() throws JsonProcessingException {
        // null分支
        when(metadataSerializerHelper.getManager(any())).thenReturn(null);

        // 异常
        TestUtils.setStaticFieldValue(MetadataSerializerHelper.class, "singleton", metadataSerializerHelper);
        GspMetadata metadata = new GspMetadata(new MetadataHeader());
        metadata.getHeader().setType("type");
        assertThrows(LcmConfigResolveException.class, () -> metadataSerializer.serialize(metadata));

        // mock content
        when(metadataSerializerHelper.getManager(any())).thenReturn(metadataContentSerializer);
        JsonNode jsonNode = mapper.readTree("{\"A\": \"a\"}");
        when(metadataContentSerializer.Serialize(any())).thenReturn(jsonNode);

        // mock extendRule
        TestUtils.setStaticFieldValue(MdExtRuleSerializerHelper.class, "singleton", mdExtRuleSerializerHelper);
        when(mdExtRuleSerializerHelper.getManager(any())).thenReturn(mdExtendRuleSerializer);
        JsonNode extRuleNode = mapper.readTree("{\"B\": \"b\"}");
        when(mdExtendRuleSerializer.serialize(any())).thenReturn(extRuleNode);
        metadata.setExtendRule(mdExtRuleContent);

        // 调用方法
        String metadataStr = metadataSerializer.serialize(metadata);
        assertTrue(metadataStr.contains("\"a\"") && metadataStr.contains("\"b\""));
    }
}